package NP;
import java.util.Iterator;
import java.util.Random;
//les certifcats pour BinPack 
public class  CertificatBinPack implements Certificat<PbBinPack>{
	//A completer

	//tableau d'objets avec les num de sac
	private int tabRepartitions[];
	private int ns;
	

	//une solution proposee dans aff
	private int aff[] = null;
	
	//constructeur d'un certificat � partir d'un pb
	public CertificatBinPack(PbBinPack p) {
		this.tabRepartitions =  new int [p.getN()];
		this.ns = p.getNbs();		
	}

	//constructeur d'un certificat � partir d'unpb et d'une solution proposee dans 1 affectation
	public CertificatBinPack(PbBinPack p, int[] aff) {
		this.tabRepartitions =  aff;
		this.ns = p.getNbs();	
	}


	//constructeur d'un certificat � partir d'un nb de sacs et d'objets
	public CertificatBinPack(int no, int ns) {
		this.tabRepartitions =  new int [no];
		this.ns =  ns;
	}
	
	public CertificatBinPack(int[] aff){
		this.tabRepartitions =  aff;
	}

	//A completer

	public Iterator<Certificat> ToutesLesInstances() {
		return new CertificatIterator(this.tabRepartitions, this.ns);
	}
	
	class CertificatIterator implements Iterator {

		private int tabNumDeSacPourObjet[];
		private int ns;
		private int indiceObjet;
		private int cpt;
		
		public CertificatIterator(int[] tabRepartitions, int ns) {
			this.tabNumDeSacPourObjet = tabRepartitions;
			this.indiceObjet = this.tabNumDeSacPourObjet.length;
			this.ns = ns;
			this.cpt = 0;
		}

		@Override
		public boolean hasNext()  {
			
			for (int i = this.tabNumDeSacPourObjet.length-1 ; i >= 0 ; i--) {
				if(this.tabNumDeSacPourObjet[i] != this.ns-1) return true;
			}
			
			return false;
		}

		@Override
		public Object next() {
			int i = 0;
			if(cpt == 0){ // Si premiere fois, on retourne le tout premier, sinon on cherche les suivants
				cpt++;
				return new CertificatBinPack(tabNumDeSacPourObjet);
			}
			cpt++;
			
			//car sac de 0 a n-1
			while(this.tabNumDeSacPourObjet[i] == this.ns - 1){
				//on reporte
				this.tabNumDeSacPourObjet[i] = 0;
				i++;
			}
			
			this.tabNumDeSacPourObjet[i]++;
			
			return new CertificatBinPack(tabNumDeSacPourObjet);
		}

		@Override
		public void remove() {
				throw new UnsupportedOperationException();
		}
		
	}

	public void alea()  {
		Random r = new Random();
		for(int i = 0; i < tabRepartitions.length; i++){ // Pour chaque Objet on choisit un sac au hasard
			tabRepartitions[i] = r.nextInt(this.ns);
		}
	}

	//algo A de verif du cours
	public boolean estCorrect(PbBinPack pb){
		
		int tabSommeObjetParSac[] = new int [pb.getNbs()];
		
		for(int i = 0; i < pb.getN(); i++){
			tabSommeObjetParSac[tabRepartitions[i]]+= pb.getP(i);
		}
	
		for(int i=0; i < pb.getNbs(); i++){				
			if(pb.getC(i) < tabSommeObjetParSac[i]) return false;
		}

		return true;
	}  

	//r�intialise le certificat au premier ds l'ordre lexico
	public void reset() {
		for(int i = 0; i < tabRepartitions.length; i++){ // Pour chaque Objet on choisit un sac au hasard
			tabRepartitions[i] =0;
		}
	}

	//affiche le certificat
	public void display() {
		for(int i = 0; i < tabRepartitions.length; i ++){
			System.out.println("objet "+i+" dans sac +"+tabRepartitions[i]);
		}
	}
	
	public String toString(){
		
		StringBuffer laString =  new StringBuffer();

		for(int i = 0; i < tabRepartitions.length; i ++){
			laString.append(tabRepartitions[i]+ " ");
		}
		
		return laString.toString();
	}


}
